﻿using dtPolyRef = System.UInt32;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace Recast
{
	public unsafe partial class RecastGlobal
	{
		public static long RC_SIZE_MAX = long.MaxValue;
		public static float FLT_MAX = 3.402823466e+38F;
		public const int RC_MAX_LAYERS_DEF = 63;
		public const int RC_MAX_NEIS_DEF = 16;

		public static HashSet<IntPtr> Ptrs = new HashSet<IntPtr>();
		public static readonly object PtrLock = new object();

		public static void* malloc(int size)
		{
			lock (PtrLock)
			{
				var ptr = Marshal.AllocHGlobal(size);
				Ptrs.Add(ptr);
				return (void*)ptr;
			}
		}
		public static void free(void* ptr)
		{
			lock (PtrLock)
			{
				var ptr1 = (IntPtr)ptr;
				if (Ptrs.Remove(ptr1))
					Marshal.FreeHGlobal(ptr1);
				else
					Debug.WriteLine($"{ptr1}已经被释放!");
			}
		}
		public static bool isfinite(float x)
		{
			return !float.IsNaN(x) && !float.IsInfinity(x);
		}
		public static float atan2f(float y, float x)
		{
			return (float)Math.Atan2(y, x);
		}
		public static float sinf(float x)
		{
			return (float)Math.Sin(x);
		}
		public static float ceilf(float x)
		{
			return (float)Math.Ceiling(x);
		}
		public static float fabsf(float x)
		{
			return Math.Abs(x);
		}
		public static float floorf(float x)
		{
			return (float)Math.Floor(x);
		}
		public static float roundf(float f)
		{
			return (float)Math.Round(f);
		}

		public unsafe static void memset(void* destination, byte value, int size)
		{
			byte* byteDestination = (byte*)destination;
			for (int i = 0; i < size; i++)
			{
				*byteDestination = value;
				byteDestination++;
			}
		}

		public static void memcpy(void* _Dst, void* _Src, int _Size)
		{
			byte* destPtr = (byte*)_Dst;
			byte* srcPtr = (byte*)_Src;
			for (int i = 0; i < _Size; i++)
			{
				destPtr[i] = srcPtr[i];
			}
		}

		public static unsafe void memmove(void* dest, void* src, int size)
		{
			byte* d = (byte*)dest;
			byte* s = (byte*)src;

			if (d < s)
			{
				// Copy forward from start to end
				for (int i = 0; i < size; i++)
				{
					d[i] = s[i];
				}
			}
			else
			{
				// Copy backward from end to start
				for (int i = size - 1; i >= 0; i--)
				{
					d[i] = s[i];
				}
			}
		}

		public static unsafe void qsort(void* basePtr, int numOfElements, int sizeOfElements, CompareItemX compareFunction)
		{
			int elementSize = sizeOfElements;
			byte* baseBytePtr = (byte*)basePtr;

			byte* temp = stackalloc byte[elementSize];
			for (int i = 0; i < numOfElements - 1; i++)
			{
				for (int j = 0; j < numOfElements - i - 1; j++)
				{
					void* a = baseBytePtr + j * elementSize;
					void* b = baseBytePtr + (j + 1) * elementSize;

					int compareResult = compareFunction(a, b);

					if (compareResult > 0)
					{
						// Swap elements a and b
						//byte* temp = stackalloc byte[elementSize];
						memset(temp, 0, sizeof(byte) * elementSize);

						memcpy(temp, a, elementSize);
						memcpy(baseBytePtr + j * elementSize, b, elementSize);
						memcpy(b, temp, elementSize);
					}
				}
			}
		}

		public delegate int CompareItemX(void* va, void* vb);

		public static float sqrtf(float x)
		{
			return (float)Math.Sqrt(x);
		}
		public static float cosf(float x)
		{
			return (float)Math.Cos(x);
		}
		public static int atoi(char* str)
		{
			int result = 0;
			bool isNegative = false;

			// 检查是否为负数
			if (*str == '-')
			{
				isNegative = true;
				str++;
			}

			// 逐个字符解析整数
			while (*str != '\0')
			{
				if (*str >= '0' && *str <= '9')
				{
					result = result * 10 + (*str - '0');
				}
				else
				{
					break;
				}

				str++;
			}

			if (isNegative)
			{
				result = -result;
			}

			return result;
		}

		public static void rcAssert<T>(T* obj)
		{
		}
		public static void rcAssert<T>(T obj)
		{
		}
		public static void dtAssert<T>(T* obj)
		{
		}
		public static void dtAssert<T>(T obj)
		{
		}

		public static T* reinterpretCast<T>(byte* buffer)
		{
			return (T*)buffer;
		}

		public static int dtMergeCorridorStartMoved(dtPolyRef* path, int npath, int maxPath, dtPolyRef* visited, int nvisited)
		{

			int furthestPath = -1;
			int furthestVisited = -1;

			// Find furthest common polygon.
			for (int i = npath - 1; i >= 0; --i)
			{
				bool found = false;
				for (int j = nvisited - 1; j >= 0; --j)
				{
					if (path[i] == visited[j])
					{
						furthestPath = i;
						furthestVisited = j;
						found = true;
					}
				}
				if (found)
					break;
			}

			// If no intersection found just return current path. 
			if (furthestPath == -1 || furthestVisited == -1)
				return npath;

			// Concatenate paths.	

			// Adjust beginning of the buffer to include the visited.
			int req = nvisited - furthestVisited;
			int orig = dtMin(furthestPath + 1, npath);
			int size = dtMax(0, npath - orig);
			if (req + size > maxPath)
				size = maxPath - req;
			if (size != 0)
				memmove(path + req, path + orig, size * sizeof(dtPolyRef));

			// Store visited
			for (int i = 0; i < req; ++i)
				path[i] = visited[(nvisited - 1) - i];

			return req + size;
		}
	}
}
